package com.lad.multithread_transactional;

import com.lad.springboot_mybatis.entity.User;
import com.lad.springboot_mybatis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 多线程情况下 事物不生效问题
 * 每个线程都开启事物，待所有线程都执行完，统一提交事物；
 * 若其中有线程出现异常，停止还未执行的任务，统一回滚
 */
@Service
public class TransactionalService {
    @Autowired
    private UserMapper userMapper;

    private static Map<Integer, List<User>> map = new HashMap<>();

    @Autowired
    private PlatformTransactionManager platformTransactionManager;//手动事物管理
    @Autowired
    private TransactionDefinition transactionDefinition;//事物

    volatile boolean flag = true;

    public void execution() {

        int size = map.entrySet().size();
//        List<TransactionStatus> list = new ArrayList<>();
//        AtomicInteger atomicInteger = new AtomicInteger(0);
        //缓存子线程与相应的事务
        Map<Thread, TransactionStatus> map1 = new HashMap<>();
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //用于主线程等待 子线程
        CountDownLatch countDownLatch = new CountDownLatch(size);

//        CountDownLatch countDownLatchMain = new CountDownLatch(1);
        try {

            for (int i = 0; i < size; i++) {
                if (!flag) {
                    System.out.println("insert error!!!");
                    return;
                }
                int finalI = i;
                executorService.execute(() -> {
                    TransactionStatus transactionStatus = null;
                    TransactionStatus transactionStatusCache = null;
                    try {
                        //因为线程复用，有可能当前线程中已经存在事务，则不再获取事务
                        transactionStatusCache = map1.get(Thread.currentThread());
                        if (transactionStatus == null) {
                            transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
                        } else {
                            transactionStatus = transactionStatusCache;
                        }
                        List<User> users = map.get(finalI);
                        userMapper.insertUsers(users);
                        System.out.println(Thread.currentThread().getName() + "执行-->" + finalI);

//                        if (finalI == 2) {
//                            int a = 1/0;
//                        }

                    } catch (Exception e) {
                        System.out.println(Thread.currentThread().getName() + "执行-->" + finalI+"--> error" + e.getMessage());
                        flag = false;
                    } finally {
                        if (transactionStatusCache == null) {
                            map1.put(Thread.currentThread(), transactionStatus);
                        }
                        countDownLatch.countDown();
                        /*try {
                            countDownLatchMain.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        if (flag){
                            platformTransactionManager.commit(transactionStatus);
                            System.out.println(Thread.currentThread().getName()+"--> 提交事物");
                        } else {
                            platformTransactionManager.rollback(transactionStatus);
                            System.out.println(Thread.currentThread().getName()+"--> 回滚事物");
                        }*/
                    }

                });

            }

            countDownLatch.await();

//            countDownLatchMain.countDown();
//            if (list.size() != size){
//                flag = false;
//            }

            for (int i = 0; i < map1.entrySet().size(); i++) {
                if (flag) {
                    executorService.execute(() -> {
                                TransactionStatus transactionStatus = map1.get(Thread.currentThread());
                                platformTransactionManager.commit(transactionStatus);
                                System.out.println(Thread.currentThread().getName()+"--> 提交事物");
                            }
                    );
                }else {
                    executorService.execute(() -> {
                                TransactionStatus transactionStatus = map1.get(Thread.currentThread());
                                platformTransactionManager.rollback(transactionStatus);
                                System.out.println(Thread.currentThread().getName()+"--> 回滚事物");
                            }
                    );
                }

            }
        } catch (Exception e) {

        }
    }

    static {
        for (int i = 0; i < 10; i++) {
            List<User> users = new ArrayList<>();
            for (int j = 1; j < 11; j++) {
                User user = new User(i * 10 + j, "zs" + i + j, "000" + i + j, "admin" + i + j);
                users.add(user);
            }
            map.put(i, users);
        }

    }

}
